package main

//选项模式
type stuffClient struct {
	conn    string
	timeout int
	retries int
}

//结构体 stuffClient 是私有的, 所以我们应该为它提供一些构造器:
//func NewStuffClient(conn string ,timeout int ,retries int) stuffClient {
//	return stuffClient{
//		conn:    conn,
//		timeout: timeout,
//		retries: retries,
//	}
//}

//--------------------------------------------------------
//我们每次调用 NewStuffClient 时都要提供 timeout 和 retries. 而大多数时候我们只想使用默认值.
//我们不能用不同的参数数量来定义多个版本的 NewStuffClient, 否则我们会得到一个类似 "NewStuffClient redeclared in this blockt" 的编译错误.
//一个方案是创建另一个不同名称的构造器:
//const (
//	DEFAULT_TIMEOUT=10
//	DEFAULT_RETRIES=10
//)
//func NewStuffClient(conn string)  stuffClient{
//	return stuffClient{
//		conn:    conn,
//		timeout: DEFAULT_TIMEOUT,
//		retries: DEFAULT_RETRIES,
//	}
//}
//func NewStuffClientWithOptions(conn string ,timeout,retries int) stuffClient {
//	return stuffClient{
//		conn:    conn,
//		timeout: timeout,
//		retries: retries,
//	}
//}
//----------------------------------------------------------------

//但是, 这有点蹩脚. 我们可以做得比这更好. 如果我们传入了一个配置对象呢:
//type StuffClientOptions struct {
//	Retries int //number of times to retry the request before giving up
//	Timeout int //connection timeout in seconds
//}
//func NewStuffClient(conn string, options StuffClientOptions) stuffClient {
//	return stuffClient{
//		conn:    conn,
//		timeout: options.Timeout,
//		retries: options.Retries,
//	}
//}
//----------------------------------------------------------------
//但是, 这也不是很好. 现在我们总是需要创建 StuffClientOptions, 并且即使我们不想指定任何选项也要传递它.
//而且我们也没有自动填充默认值, 除非我们在代码中添加了一堆检查,
//或者我们可以传入一个 DefaultStuffClientOptions 变量 (也不好, 因为它可以在一个地方修改导致其他地方有问题).

type StuffClientOption func(options *StuffClientOptions)
type StuffClientOptions struct {
	Retries int //number of times to retry the request before giving up
	Timeout int //connection timeout in seconds
}

func WithRetries(r int) StuffClientOption {
	return func(options *StuffClientOptions) {
		options.Retries = r
	}
}
func WithTimeout(t int) StuffClientOption {
	return func(options *StuffClientOptions) {
		options.Timeout = t
	}
}

var defaultStuffClientOption = StuffClientOptions{
	Retries: 3,
	Timeout: 2,
}

func NewStuffClient(conn string, opts ...StuffClientOption) stuffClient {
	options := defaultStuffClientOption
	for _, opt := range opts {
		opt(&options)
	}
	return stuffClient{
		conn:    conn,
		timeout: options.Timeout,
		retries: options.Retries,
	}
}
